/*
 * Copyright (c) 2017.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package mybatisgen.plugin;

import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.List;

@Slf4j
public class SelectOneByExamplePlugin extends PluginAdapter {
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        Method method = new Method("selectOneByExample");
        FullyQualifiedJavaType returnType = introspectedTable.getRules().calculateAllFieldsClass();
        method.setReturnType(returnType);
        FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
        method.addParameter(new Parameter(type, "example"));
        method.setAbstract(true);
        interfaze.addMethod(method);
        return super.clientGenerated(interfaze, introspectedTable);
    }

    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        XmlElement selectOneElement = new XmlElement("select");
        selectOneElement.addAttribute(new Attribute("id", "selectOneByExample"));
        StringBuilder sb;
        XmlElement ifElement;
        if (introspectedTable.hasBLOBColumns()) {
            selectOneElement.addAttribute(new Attribute("resultMap", introspectedTable.getResultMapWithBLOBsId()));
            selectOneElement.addAttribute(new Attribute("parameterType", introspectedTable.getExampleType()));
            selectOneElement.addElement(new TextElement("select"));
            sb = new StringBuilder();
            if (StringUtility.stringHasValue(introspectedTable.getSelectByExampleQueryId())) {
                sb.append('\'');
                sb.append(introspectedTable.getSelectByExampleQueryId());
                sb.append("' as QUERYID,");
                selectOneElement.addElement(new TextElement(sb.toString()));
            }

            selectOneElement.addElement(XmlElementGeneratorTools.getBaseColumnListElement(introspectedTable));
            selectOneElement.addElement(new TextElement(","));
            selectOneElement.addElement(XmlElementGeneratorTools.getBlobColumnListElement(introspectedTable));
            sb.setLength(0);
            sb.append("from ");
            sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime());
            selectOneElement.addElement(new TextElement(sb.toString()));
            selectOneElement.addElement(XmlElementGeneratorTools.getExampleIncludeElement(introspectedTable));
            ifElement = new XmlElement("if");
            ifElement.addAttribute(new Attribute("test", "orderByClause != null"));
            ifElement.addElement(new TextElement("order by ${orderByClause}"));
            selectOneElement.addElement(ifElement);
            selectOneElement.addElement(new TextElement("limit 1"));
        } else {
            selectOneElement.addAttribute(new Attribute("resultMap", introspectedTable.getBaseResultMapId()));
            selectOneElement.addAttribute(new Attribute("parameterType", introspectedTable.getExampleType()));
            selectOneElement.addElement(new TextElement("select"));
            sb = new StringBuilder();
            if (StringUtility.stringHasValue(introspectedTable.getSelectByExampleQueryId())) {
                sb.append('\'');
                sb.append(introspectedTable.getSelectByExampleQueryId());
                sb.append("' as QUERYID,");
                selectOneElement.addElement(new TextElement(sb.toString()));
            }

            selectOneElement.addElement(XmlElementGeneratorTools.getBaseColumnListElement(introspectedTable));
            sb.setLength(0);
            sb.append("from ");
            sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime());
            selectOneElement.addElement(new TextElement(sb.toString()));
            selectOneElement.addElement(XmlElementGeneratorTools.getExampleIncludeElement(introspectedTable));
            ifElement = new XmlElement("if");
            ifElement.addAttribute(new Attribute("test", "orderByClause != null"));
            ifElement.addElement(new TextElement("order by ${orderByClause}"));
            selectOneElement.addElement(ifElement);
            selectOneElement.addElement(new TextElement("limit 1"));
        }

        document.getRootElement().addElement(selectOneElement);
        return true;
    }
}